/*
 * 此文件为地图应用的基础功能框架，主要包括openlayers常用的变量和创建对象的工厂方法
 * 此文件是与项目完全解耦的，无需改动即可移植到其他项目中使用
 */

(function (global, factory) {
    global.xdmap = factory(global);
})(typeof window !== 'undefined' ? window : this, function (global) {
    // 构造函数
    function XdMap() {
    }

    var xdmap = new XdMap();
    var x_PI = 3.14159265358979324 * 3000.0 / 180.0,
        PI = 3.1415926535897932384626,
        a = 6378245.0,
        ee = 0.00669342162296594323;
    /**
     * 扩展xdmap对象属性和方法
     * 传入新的对象，将该对象本身拥有的方法和属性复制给xdmap
     *
     * @param {Object} object
     */
    XdMap.prototype.extend = function (object) {
        for (var key in object) {
            if (object.hasOwnProperty(key)) {
                xdmap[key] = object[key];
            }
        }
    };
    //init
    xdmap.extend({
        initGaode: function () {
            var gaodeMapLayer = new ol.layer.Tile({
                source: new ol.source.XYZ({
                    crossOrigin: 'anonymous',
                    url: 'http://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}', //正常版
                    //url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'//字大版
                })
            });

            return gaodeMapLayer;
        },
        /**
         * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
         * 即 百度 转 谷歌、高德
         * @param bd_lon
         * @param bd_lat
         * @returns {*[]}
         */
        bd09togcj02: function (bd_lon, bd_lat) {
            var bd_lon = +bd_lon;
            var bd_lat = +bd_lat;
            var x = bd_lon - 0.0065;
            var y = bd_lat - 0.006;
            var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
            var gg_lng = z * Math.cos(theta);
            var gg_lat = z * Math.sin(theta);
            return [gg_lng, gg_lat]
        },
        //百度坐标转84
        bdto84: function(center){
            var bd_lon = center.x;
            var bd_lat = center.y;
            var x = bd_lon - 0.0065;
            var y = bd_lat - 0.006;
            var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_PI);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_PI);
            var gg_lng = z * Math.cos(theta);
            var gg_lat = z * Math.sin(theta);
            return xdmap.gcj02towgs84(gg_lng, gg_lat)
        },
        /**
         * GCJ02 转换为 WGS84
         * @param lng
         * @param lat
         * @returns {*[]}
         */
        gcj02towgs84: function (lng, lat) {
            var x_PI = 3.14159265358979324 * 3000.0 / 180.0,
                PII = 3.1415926535897932384626,
                aa = 6378245.0,
                ees = 0.00669342162296594323;
            var lat = +lat;
            var lng = +lng;
            if (this.out_of_china(lng, lat)) {
                return [lng, lat]
            } else {
                var dlat = this.transformlat(lng - 105.0, lat - 35.0);
                var dlng = this.transformlng(lng - 105.0, lat - 35.0);
                var radlat = lat / 180.0 * PII;
                var magic = Math.sin(radlat);
                magic = 1 - ees * magic * magic;
                var sqrtmagic = Math.sqrt(magic);
                dlat = (dlat * 180.0) / ((aa * (1 - ees)) / (magic * sqrtmagic) * PII);
                dlng = (dlng * 180.0) / (aa / sqrtmagic * Math.cos(radlat) *PII);
                var mglat = lat + dlat;
                var mglng = lng + dlng;
                return [lng * 2 - mglng, lat * 2 - mglat]
            }
        },
        /*经纬度转墨卡托投影坐标*/
        lonlatTomct:function (lonlat) {
            var mercator={x:0,y:0};
            var x = lonlat.x *20037508.34/180;
            var y = Math.log(Math.tan((90+lonlat.y)*Math.PI/360))/(Math.PI/180);
            y = y *20037508.34/180;
            mercator.x = x;
            mercator.y = y;
            return mercator ;
        },
        /**
         * WGS84转GCj02
         * @param lng
         * @param lat
         * @returns {*[]}
         */
        wgs84togcj02: function (lng, lat) {
            var lat = +lat;
            var lng = +lng;
            if (this.out_of_china(lng, lat)) {
                return [lng, lat]
            } else {
                var dlat = this.transformlat(lng - 105.0, lat - 35.0);
                var dlng = this.transformlng(lng - 105.0, lat - 35.0);
                var radlat = lat / 180.0 * PI;
                var magic = Math.sin(radlat);
                magic = 1 - ee * magic * magic;
                var sqrtmagic = Math.sqrt(magic);
                dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
                dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
                var mglat = lat + dlat;
                var mglng = lng + dlng;
                this.gcj02tobd09(mglng, mglat);
            }
        },
        /**
         * MCT->GCJ02MCT
         * @param lng
         * @param lat
         * @returns {*[]}
         */
        mctToGcj02Mct: function (point) {
            var mct = ol.proj.transform(point, 'EPSG:3857', 'EPSG:4326');
            var wgs = this.wgs84togcj02(mct[0], mct[1]);
            var rltMct = ol.proj.transform(wgs, 'EPSG:4326', 'EPSG:3857');
            this.gcj02tobd09(rltMct);
        },
        /**
         * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
         * 即谷歌、高德 转 百度
         * @param lng
         * @param lat
         * @returns {*[]}
         */
        gcj02tobd09: function (lng, lat) {
            var lat = +lat;
            var lng = +lng;
            var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
            var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
            var bd_lng = z * Math.cos(theta) + 0.0065;
            var bd_lat = z * Math.sin(theta) + 0.006;
            return [bd_lng, bd_lat]
        },
        //坐标转换工具
        transformlat: function (lng, lat) {
            var lat = +lat;
            var lng = +lng;
            var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
            ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
            return ret
        },
        transformlng: function (lng, lat) {
            var lat = +lat;
            var lng = +lng;
            var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
            ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
            return ret
        },
        /** 判断是否在国内，不在国内则不做偏移
         * @param lng
         * @param lat
         * @returns {boolean}
         */
        out_of_china: function (lng, lat) {
            var lat = +lat;
            var lng = +lng;
            // 纬度3.86~53.55,经度73.66~135.05
            return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55);
        },
        initTianditu: function () {
            var base = new Array();
            var tian_di_tu_road_layer = new ol.layer.Tile({
                title: "天地图路网",
                source: new ol.source.XYZ({
                    //crossOrigin: 'anonymous',
                    url: "http://t3.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}"
                })
            });
            base.push(tian_di_tu_road_layer);
            var tian_di_tu_annotation = new ol.layer.Tile({
                title: "天地图文字标注",
                source: new ol.source.XYZ({
                    //crossOrigin: 'anonymous',
                    url: 'http://t3.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}'
                })
            });
            base.push(tian_di_tu_annotation);
            return base;
        },
        initWeiji: function () {
            var weiji = new ol.layer.Tile({
                source: new ol.source.OSM(),
            });
            weiji.set('id','base');
            return weiji;
        },
        initSatellite: function () {
            // var url = 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965';
            // var url ='http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009253!3m9!2szh-CN!3sCN!5e18!12m1!1e50!12m3!1e37!2m1!1ssmartmaps!4e0&token=2064';
            // var url ="http://t0.tianditu.com"+"/DataServer?T="+"img_w"+"&x="+col+"&y="+row+"&l="+level;
            var url = "http://t{0-7}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}";
            var sateLayer = new ol.layer.Tile({
                title: "卫星图",
                baseLayer: true,
                source: new ol.source.XYZ({
                    crossOrigin: 'anonymous',
                    url: url
                })
            });
            return sateLayer;
        },
        initSatellites: function () {
            // var url = 'http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965';
            // var url ='http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009253!3m9!2szh-CN!3sCN!5e18!12m1!1e50!12m3!1e37!2m1!1ssmartmaps!4e0&token=2064';
            // var url ="http://t0.tianditu.com"+"/DataServer?T="+"img_w"+"&x="+col+"&y="+row+"&l="+level;
            var url = "http://t{0-7}.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}";
            var sateLayers = new ol.layer.Tile({
                title: "卫星图",
                baseLayer: true,
                source: new ol.source.XYZ({
                    crossOrigin: 'anonymous',
                    url: url
                })
            });
            return sateLayers;
        },
        initGoogle: function () {
            // var url ='http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965';
            var url = 'http://www.google.cn/maps/vt/pb=!1m4!1m3!1i{z}!2i{x}!3i{y}!2m3!1e0!2sm!3i380072576!3m8!2szh-CN!3scn!5e1105!12m4!1e68!2m2!1sset!2sRoadmap!4e0!5m1!1e0'
            var googleLayer = new ol.layer.Tile({
                visible: true,
                source: new ol.source.XYZ({
                    crossOrigin: 'anonymous',
                    url: url
                })
            });
            return googleLayer;
        },
        // initGXD: function () {
        //     var gxd = new ol.layer.Tile({
        //         extent: [7107053.740285003, -80822.9193149989, 16061315.281015012, 8587942.610615],
        //         source: new ol.source.TileArcGISRest({
        //             url: "http://lbsapi.cindata.cn/gis/v1/services/export",
        //             params: {
        //                 mapCode: '1_base_map_fe9e51abd96b7a041ab6f883eda91349',
        //                 keyCode: '78b8c098b5694cf09fcd9b18ce94e7e7'
        //             }
        //         })
        //     })
        //     gxd.set('id', 'base');
        //     gxd.setZIndex(0);
        //     return gxd;
        // },
        initGXD:function() {
            var gxd = new ol.layer.Tile({
                extent: [7107053.740285003, -80822.9193149989, 16061315.281015012, 8587942.610615],
                source: new ol.source.TileArcGISRest({
                    url: "http://lbsapi.cindata.cn/gis/v1/services/export",
                    params: {
                        mapCode: '1_base_map_fe9e51abd96b7a041ab6f883eda91349',
                        keyCode: '78b8c098b5694cf09fcd9b18ce94e7e7'
                    }
                })
            })
            gxd.set('id', 'base');
            gxd.setZIndex(0);
            return gxd;
        },
        initLocalHost:function(){
            var openStreetMapLayer = new ol.layer.Tile({
                //使用XYZ的方式加载瓦片图
                source: new ol.source.XYZ({
                    //OpenStreetMap的瓦片URL，代码中替换为相应的URL
                    url: 'http://localhost:8080/tiles/{z}/{x}/{y}.png'
                })
            });
            openStreetMapLayer.set('id','base');
            return openStreetMapLayer;
        },
        initBaidu: function () {
            // 自定义分辨率和瓦片坐标系
            var resolutions = [];
            var maxZoom = 18;
            // 计算百度使用的分辨率
            for (var i = 0; i <= maxZoom; i++) {
                resolutions[i] = Math.pow(2, maxZoom - i);
            }
            var tilegrid = new ol.tilegrid.TileGrid({
                origin: [0, 0],    // 设置原点坐标
                resolutions: resolutions    // 设置分辨率
            });
            var projection = ol.proj.get("EPSG:3857");
            var baiduSource = new ol.source.TileImage({
                projection: projection,
                tileGrid: tilegrid,
                tileUrlFunction: function (tileCoord, pixelRatio, proj) {
                    if (!tileCoord) {
                        return "";
                    }
                    var z = tileCoord[0];
                    var x = tileCoord[1];
                    var y = tileCoord[2];
                    if (x < 0) {
                        x = "M" + (-x);
                    }
                    if (y < 0) {
                        y = "M" + (-y);
                    }

                    return "http://online3.map.bdimg.com/onlinelabel/?qt=tile&x=" + x + "&y=" + y + "&z=" + z + "&styles=pl&udt=20151021&scaler=1&p=1";
                }
            });
            // 百度地图层
            var baidu = new ol.layer.Tile({
                source: baiduSource
            });


            return baidu;
        },
        initGoogle: function () {
            var url = 'http://mt{0-1}.google.cn/maps/vt?lyrs=s@198&hl=zh-CN&gl=CN&&x={x}&y={y}&z={z}';
            // var url ='http://www.google.cn/maps/vt?pb=!1m5!1m4!1i{z}!2i{x}!3i{y}!4i256!2m3!1e0!2sm!3i342009817!3m9!2szh-CN!3sCN!5e18!12m1!1e47!12m3!1e37!2m1!1ssmartmaps!4e0&token=32965';
            var googleLayer = new ol.layer.Tile({
                visible: true,
                source: new ol.source.XYZ({
                    crossOrigin: 'anonymous',
                    url: url
                })
            });
            return googleLayer;
        },
        weijiSource: function () {
            var weijiMapSource = new ol.source.OSM();
            return weijiMapSource;
        },
        tiandiSource: function () {
            var tian_di_tu_road_source = new ol.source.XYZ({
                url: "http://t3.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}"
            })
            return tian_di_tu_road_source;
        },
        tiandiSource2: function () {
            var tian_di_tu_annotation_source = new ol.source.XYZ({
                url: 'http://t3.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}'
            })
            var tianditu = new ol.layer.Tile({
                source: tian_di_tu_annotation_source,
            });
            return tianditu;
        },
        satelliteSource: function () {
            var url = "http://t{0-7}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}";
            var sateLayerSource = new ol.source.XYZ({
                crossOrigin: 'anonymous',
                url: url
            })
            return sateLayerSource;
        },
        gxdSource: function(){
            var url = 'http://111.40.214.181/arcgis/rest/services/comm/China/MapServer';
            var gxdSource =  new ol.source.TileArcGISRest({
                url: url
            })
            return gxdSource;
        },
        layer440100:function(){
            var openStreetMapLayer = new ol.layer.Tile({
                //使用XYZ的方式加载瓦片图
                source: new ol.source.XYZ({
                    //OpenStreetMap的瓦片URL，代码中替换为相应的URL
                    url: 'http://map-geoserver.cindata.cn/tiles/440100/{z}/{x}/{y}.png'
                })
            });
            openStreetMapLayer.set('id','base');
            return openStreetMapLayer;
        },
        layer440300:function() {
            var openStreetMapLayer = new ol.layer.Tile({
                //使用XYZ的方式加载瓦片图
                source: new ol.source.XYZ({
                    //OpenStreetMap的瓦片URL，代码中替换为相应的URL
                    url: 'http://map-geoserver.cindata.cn/tiles/440300/{z}/{x}/{y}.png'
                })
            });
            openStreetMapLayer.set('id', 'base');
            return openStreetMapLayer;
        },
        mapInit: function (id, zoom, center) {
            // 空的地图对象
            var map = xdmap.getMapInstance();
            // 目标html元素
            map.setTarget(id);
            
            // 维基地图
            // var weiji = this.initWeiji();
            // map.addLayer(weiji);
            
            // var layer440100 = this.layer440100();
            // var layer440300 = this.layer440300();
            // map.addLayer(layer440300);
            // map.addLayer(layer440100)

            // 国信达地图
            var gxd = this.initGXD()
            map.addLayer(gxd)

            // var base = this.initLocalHost();
            // map.addLayer(base)
            var view = new ol.View({
                zoom: zoom,
                center: center,
                projection: 'EPSG:3857',
                maxZoom: 18,
                minZoom: 6
            });
            map.setView(view);
            return map;
        },
    });
    // projection
    xdmap.extend({
        // 球面墨卡托坐标系
        proj_3857: ol.proj.get('EPSG:3857'),
        // 经纬度坐标系
        proj_4326: ol.proj.get('EPSG:4326')
    });
    // format
    xdmap.extend({
        // geojson地图格式
        formatGeojson: new ol.format.GeoJSON()
    });
    // control
    xdmap.extend({
        /**
         * 得到openlayers默认控件组
         *
         * @returns {ol.Collection < ol.control.Control >}
         */
        getDefaultControls: function () {
            return ol.control.defaults();
        }
    });
    // Feature
    xdmap.extend({
        /**
         * 由Point接口数据返回ol.Feature
         *
         * @param {Point} point
         * @returns {ol.Feature}
         */
        getFeature: function (point) {
            var feature = new ol.Feature();
            feature.setGeometry(new ol.geom.Point(point.coordinates));
            feature.setId(point.id);
            feature.setProperties({
                zylx: point.zylx,
                zylxId: point.zylxId
            });
            return feature;
        },
        /**
         * 以Point类型数据返回ol.Feature数组
         *
         * @param {Point[]} points
         * @returns {ol.Feature[]}
         */
        getFeaturesForPoints: function (points) {
            var _this = this;
            var features = new Array;
            points.forEach(function (v, i, a) {
                var feature = _this.getFeature(v);
                features.push(feature);
            });
            return features;
        },
        /**
         * 判断ol.Feature是否为聚合类型
         *
         * @param {ol.Feature} feature
         * @returns {boolean}
         */
        isClusterFeature: function (feature) {
            return feature.get('features') !== undefined ? true : false;
        },
        /**
         * 返回ol.Feature的坐标/适用于Point点
         *
         * @param {ol.Feature} feature
         * @returns {ol.Coordinate}
         */
        getFeatureCoordinates: function (feature) {
            return feature.getGeometry().getCoordinates();
        }
    });
    // Map
    xdmap.extend({
        /**
         * 获取map对象实例，
         * 多以单例出现，若需显示多个地图，则多次生成，分别以变量标记
         *
         * @returns {ol.Map}
         */
        getMapInstance: function () {
            return new ol.Map({});
        }
    });
    // layer
    xdmap.extend({
        /**
         * 获取空的矢量图层
         *
         * @returns {ol.layer.Vector}
         */
        getBlankVector: function () {
            return new ol.layer.Vector({
                source: new ol.source.Vector({})
            });
        },
        /**
         * 获取空的聚合矢量图层
         *
         * @returns {ol.layer.Vector}
         */
        getBlankCluster: function () {
            return new ol.layer.Vector({
                source: new ol.source.Cluster({
                    source: new ol.source.Vector()
                })
            });
        },
        /**
         * 获取XYZ瓦片图层
         * 通过替换地图服务url，使用不同的底图
         * 以天地图为例，访问天地图，通过网络请求查看其url，如：
         * http://t0.tianditu.com/DataServer?T=vec_c&x=208&y=80&l=9
         * 以{x/y/z}形式替换数字:
         * http://t0.tianditu.com/DataServer?T=vec_c&x={x}&y={y}&l={z}
         * 以此作为url传入即可
         *
         * @param {string} url
         * @param {ol.proj.Projection} [projection]
         * @returns {ol.layer.Tile}
         */
        getXYZTile: function (url, projection) {
            var projection_ = projection ? projection : xdmap.proj_4326;
            return new ol.layer.Tile({
                source: new ol.source.XYZ({
                    projection: projection_,
                    // crossOrigin: 'anonymous',
                    url: url
                })
            });
        },
        /**
         * XYZ图层高级方法，若底图服务与常规情况不匹配可使用此函数
         * 常见于z等级存在大小变化，如正常208，80，9的情况变成208，80，8/10，可通过此函数调节
         * 通过options对象传参，
         * options.zOffset=-1,可是url中z减一，
         * 若有其他特殊情况，需修改此函数
         *
         * @param {any} options
         * @returns
         */
        getXYZTileAdvanced: function (options) {
            var options_ = typeof options === 'object' ? options : {}, url = options_.url,
                projection = options_.projection ? options_.projection : xdmap.proj_4326,
                zOffset = options_.zOffset ? options_.zOffset : 0;
            return new ol.layer.Tile({
                source: new ol.source.XYZ({
                    projection: projection,
                    tileUrlFunction: function (coordinate) {
                        var z = coordinate[0] + zOffset, x = coordinate[1], y = -coordinate[2] - 1,
                            url_ = url.replace('{x}', x.toString()).replace('{y}', y.toString()).replace('{z}', z);
                        return url_;
                    }
                })
            });
        }

    });
    // overlay
    xdmap.extend({
        overlay: {
            /*
        * 创建Overly
        * */
            createOverlay: function (id, div, center, offset) {
                if (!offset) {
                    offset = [0, 0]
                }
                var overlay = new ol.Overlay({
                    id: id,
                    element: div,
                    position: center,
                    offset: offset,
                });
                return overlay;
            },
            /*
             * 创建Overly
             * */
            addOverlay: function (overlay) {
                map.addOverlay(overlay)
            },
            /*
            * 根据overlay获取id
            * */
            getOvelayId: function (overlay) {
                return overlay.getId();
            },
            /*
             * 根据overlay获取ele元素
             * */
            getElement: function (overlay) {
                return overlay.getElement();
            },
            /*
            * 根据overlay获取overlay坐标
            * */
            getOverlayPosition: function (overlay) {
                return overlay.getPosition();
            },
            /*
            * 设置overlay id
            * */
            setOverlyId: function (overlay, id) {
                overlay.setId(id);
            },
            /*
            * 设置overlay 位置
            * */
            setOverlyPosition: function (overlay, point) {
                overlay.setPosition(point);
            },
            /*
            * 设置overly ele元素
            * */
            setOverlayElement: function (overlay, ele) {
                overlay.setElement(overlay);
            },
            /*
            * 设置overly id
            * */
            setOverlyId: function (overlay, id) {
                overlay.setId(id);
            },
            /*
            * 根据overly对象删除overlay
            * */
            removeOverlay: function (overly) {
                map.removeOverlay(overly)
            },
            /*
            * 根据id删除overlay
            * */
            removeOverlayById: function (id) {
                map.getOverlays().forEach(function (overly) {
                    var oid = overly.getId();
                    if (id == oid) {
                        map.removeOverlay(overly)
                    }
                })
            },
            /*
            * 清除所有overlays
            * */
            removeAllOverlays: function () {
                map.getOverlays().clear();
            },
            /*
            * 隐藏所有overlays
            * */
            hideAllOverlays: function () {
                map.getOverlays().forEach(function (t) {
                    if (t) {
                        var ele = overlay.getElement();
                        ele.style.display = 'none'
                    }
                })
            }
        }
    });
    // View
    xdmap.extend({
        /**
         * 以动画形式重设地图中心点
         *
         * @param {ol.View} view
         * @param {ol.Coordinate} center
         */
        setCenter: function (view, center) {
            view.animate({
                center: center
            });
        }
    });
    // interaction
    xdmap.extend({
        /**
         * 返回默认的地图交互数组
         *
         * @returns {ol.Collection < ol.interaction.Interaction >}
         */
        getDefaultInteractions: function () {
            return ol.interaction.defaults();
        },
        resetDefaultInteractions: function (map) {
            map.getInteractions().clear();
            map.getInteractions().extend(map.getInteractions().getArray());
        }
    });
    // style
    xdmap.extend({
        /**
         * 返回图标形式的特征点样式
         *
         * @param {string} url
         * @returns {ol.style.Style}
         */
        getIconStyle: function (url) {
            return new ol.style.Style({
                image: new ol.style.Icon({
                    src: url
                })
            });
        },
        /**
         * 返回一个圆形的特征点样式
         *
         * @param {any} options
         * @returns {ol.style.Style}
         */
        getCircleStyle: function (options) {
            var options_ = typeof options === 'object' ? options : {};
            return new ol.style.Style({
                image: new ol.style.Circle({
                    radius: options_.radius,
                    fill: new ol.style.Fill({
                        color: 'blue'
                    })
                }),
                text: new ol.style.Text({
                    text: typeof options_.text !== 'undefined' ? options_.text : '',
                    fill: new ol.style.Fill({
                        color: '#ffffff'
                    })
                })
            });
        },
        /**
         * 创建通用的矢量图层样式函数，
         * 各元素返回其自身的样式
         *
         * @param {any} feature
         * @returns {Function}
         */
        getVectorStyleFunction: function (feature) {
            return function (feature) {
                return feature.getStyle();
            };
        },
        /**
         * 创建通用的聚合类矢量图层样式函数，
         * 聚合元素内部包含多个元素时，以圆形加数字形式显示，
         * 聚合元素内部仅包含一个元素时，返回该元素的样式
         *
         * @param {any} feature
         * @returns {Function}
         */
        getClusterStyleFunction: function () {
            return function (feature) {
                var style, originFeatures = feature.get('features'), length = originFeatures.length;
                if (length > 1) {
                    style = new ol.style.Style({
                        image: new ol.style.Circle({
                            radius: 12,
                            stroke: new ol.style.Stroke({
                                color: '#fff'
                            }),
                            fill: new ol.style.Fill({
                                color: '#2196f3'
                            })
                        }),
                        text: new ol.style.Text({
                            text: String(length),
                            fill: new ol.style.Fill({
                                color: '#ffffff'
                            }),
                            scale: 1.2
                        })
                    });
                }
                else {
                    var feature_1 = originFeatures[0];
                    style = feature_1.getStyle();
                }
                feature.setStyle(style);
                return style;
            };
        }
    });

    //URL params
    xdmap.extend({

        //获取url参数
        getUrlParams: function (url) {
            var params = [];
            var args = url.split("?");
            if (args.length == 1) {
                return null;
            }
            if (args[1] == '') {
                return null; //参数为空
            } else {
                var arrParam = args[1].split("&");
                arrParam.forEach(function (val) {
                    var key = val.split('=')[0];
                    var value = val.split('=')[1];
                    params[key] = value;
                })
                return params;
            }
        }
    });
    xdmap.extend({
        getFeaturesForExtent: function (source, ext, mousePosition) {
            if (source == null) {
                return null;
            } else {
                var resultFeatures = source.getFeaturesInExtent(ext);
                var minDistance = 0;
                var resultFeature = null;
                resultFeatures.forEach(function (feature) {
                    var point = feature.getGeometry().getCenter();
                    var distance = new ol.Sphere(6378137).haversineDistance(point, mousePosition);
                    if (minDistance == 0) {
                        minDistance = distance;
                        resultFeature = feature;
                    } else {
                        if (distance < minDistance) {
                            minDistance = distance;
                            resultFeature = feature;
                        }
                    }
                })
                return resultFeature;
            }
        }
    })

    /*
    * zoom
    * */
    xdmap.extend({
        zoomIn: function () {
            var zoom = map.getView().getZoom();
            zoom += 1;
            map.setZoom(zoom);
            return zoom;
        },
        zoomOut: function () {
            var zoom = map.getView().getZoom();
            zoom -= 1;
            map.setZoom(zoom);
            return zoom;
        },
        getZoom: function () {
            return map.getView().getZoom();
        },
        setZoom: function (zoom) {
            map.getView().setZoom(zoom)
        }
    })
    //commom
    xdmap.extend({
        tool:{
            //每n个字符一换行
            strWrap: function (str, count) {
                var total = 0;
                var result = '';
                var charts = new Array();
                if(str!=null) {
                    if (str.length <= count) {
                        return str;
                    } else {
                        var index = 0;
                        var chars = str.split('');
                        chars.forEach(function (char) {
                            index++;
                            total++;
                            result += char;
                            if (index == count) {
                                index = 0;
                                if (chars.length != total) {
                                    result += '\n';
                                }
                            }
                        })
                    }
                }
                return result;
            },
            /*
            * 创建feature从wkt格式数据
            * */
            createFeatureForWKT: function (strWKT) {
                var format = new ol.format.WKT();
                var feature = format.readFeature(strWKT);
                return feature;
            },
            /*
            * ep3转ep4
            * */
            epsg3ToEpsg4:function(point) {
                return ol.proj.transform(point, 'EPSG:3857', 'EPSG:4326')
            },
            /*
            * ep4转ep3
            * */
            epsg4ToEpsg3:function(point) {
                return ol.proj.transform(point, 'EPSG:4326', 'EPSG:3857')
            },
            /*
            * 添加数组remove方法
            * */
            addArrRemove:function () {
                Array.prototype.remove = function(val) {
                    var index = this.indexOf(val);
                    if (index > -1) {
                        this.splice(index, 1);
                    }
                };
            }
        },
    })

    xdmap.extend({
        /*
        * 清除除底层图层之外所有图层
        * */
        removeAllLayers:function () {
            map.getLayers().forEach(function (t) {
                if (t) {
                    if (t.get('id') != "base") {
                        map.removeLayer(t);
                    }
                }
            })
        },
        /*
        * 隐藏除底层图层之外所有图层
        * */
        hideAllLayers:function (map) {
            map.getLayers().forEach(function (t) {
                if (t) {
                    if (t.get('id') != "base") {
                        t.setVisible(false);
                    }
                }
            })
        }
    })

    return xdmap;
});